package com.app.framework.orm.util;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.app.framework.exception.ORMException;
import com.app.framework.orm.ActiveRecord;
import com.app.framework.util.JSONUtil;

public class ClassHelper {
	
	/**
	 * cglib代理标志
	 */
	private static final String CGLIB_PROXY_CLASS_FLAG = "EnhancerByCGLIB";
	/**
	 * 简单字段的类型class
	 * key 类型classsimplename
	 */
	private static Map<String,SimpleFieldType> simpleTypeClass;
	/**
	 * 索引类型class
	 * key classsimplename value 数据库字段类型
	 */
	private static Map<String,String> indexTypeClass;
	
	static {
		//加载两个静态成员变量
		simpleTypeClass = new HashMap<String,SimpleFieldType>();
		indexTypeClass = new HashMap<String,String>();
		loadIndexType();
		loadSimpleClass();
	}
	
	private static void loadSimpleClass() {
		simpleTypeClass.put(String.class.getSimpleName(), SimpleFieldType.EString);
		simpleTypeClass.put(Integer.class.getSimpleName(),SimpleFieldType.EInteger);
		simpleTypeClass.put("int",SimpleFieldType.EInteger);
		simpleTypeClass.put(Double.class.getSimpleName(),SimpleFieldType.EDouble);
		simpleTypeClass.put("double",SimpleFieldType.EDouble);
		simpleTypeClass.put(Float.class.getSimpleName(),SimpleFieldType.EFloat);
		simpleTypeClass.put("float",SimpleFieldType.EFloat);
		simpleTypeClass.put(Long.class.getSimpleName(),SimpleFieldType.ELong);
		simpleTypeClass.put("long",SimpleFieldType.ELong);
		simpleTypeClass.put(Character.class.getSimpleName(),SimpleFieldType.ECharacter);
		simpleTypeClass.put("char",SimpleFieldType.ECharacter);
		simpleTypeClass.put(Short.class.getSimpleName(),SimpleFieldType.EShort);
		simpleTypeClass.put("short",SimpleFieldType.EShort);
		simpleTypeClass.put(Byte.class.getSimpleName(),SimpleFieldType.EByte);
		simpleTypeClass.put("byte",SimpleFieldType.EByte);
		simpleTypeClass.put(Boolean.class.getSimpleName(),SimpleFieldType.EBoolean);
		simpleTypeClass.put("boolean",SimpleFieldType.EBoolean);
	}
	
	private static void loadIndexType() {
		indexTypeClass.put(String.class.getSimpleName(), "string");
		indexTypeClass.put(Character.class.getSimpleName(), "string");
		indexTypeClass.put("char", "string");
		indexTypeClass.put(Integer.class.getSimpleName(), "integer");
		indexTypeClass.put("int", "integer");
		indexTypeClass.put(Byte.class.getSimpleName(), "integer");
		indexTypeClass.put("byte", "integer");
		indexTypeClass.put(Short.class.getSimpleName(), "integer");
		indexTypeClass.put("short", "integer");
		indexTypeClass.put(Float.class.getSimpleName(), "float");
		indexTypeClass.put("float", "float");
		indexTypeClass.put(Double.class.getSimpleName(), "double");
		indexTypeClass.put("double", "double");
		indexTypeClass.put(Long.class.getSimpleName(), "long");
		indexTypeClass.put("long", "long");
	}
	
	
	public static boolean isSimpleClass(Class<?> type) {
		if(simpleTypeClass.containsKey(type.getSimpleName())) {
			return true;
		}
		return false;
	}
	
	public static String checkIndexType(Class<?> fieldType) throws ORMException {
		String result = indexTypeClass.get(fieldType.getSimpleName());
		if(result == null) {
			throw new ORMException("index type not supported: " + fieldType);
		}
		return result;
	}
	
	public static boolean isList(Class<?> type) {
		if(List.class.isAssignableFrom(type)) {
			return true;
		}
		return false;
	}
	
	public static boolean isMap(Class<?> type) {
		if(Map.class.isAssignableFrom(type)){
			return true;
		}
		return false;
	}
	
	public static boolean isRecord(Class<?> type) {
		if(ActiveRecord.class.isAssignableFrom(type)){
			return true;
		}
		return false;
	}
	
	public static Object getSimpleClassValue(Map<String,?> jsonMap,String fieldName,Class<?> fieldType) {
		if(jsonMap == null) {
			return null;
		}
		if(jsonMap.containsKey(fieldName)) {
			Object obj = jsonMap.get(fieldName);
			if(obj != null) {
				return simpleTypeClass.get(fieldType.getSimpleName()).parse(obj.toString());
			}
 		}
		return null;
	}
	
	public static Object getSimpleClassValue(String value,Class<?> fieldType) {
		
		return simpleTypeClass.get(fieldType.getSimpleName()).parse(value);
	}

	/**
	 * 获取cglib的被代理类
	 * @param clz
	 * @return
	 */
	public static Class<?> getRecordClass(Class<?> clz) {
		Class<?> ret = clz;
		if(isCglibProxyClass(clz)) {
			ret = clz.getSuperclass();
		}
		return ret;
	}
	/**
	 * 判断class是否被cglib代理
	 * @param clz
	 * @return
	 */
	public static boolean isCglibProxyClass(Class<?> clz) {
		
		return clz.getName().indexOf(CGLIB_PROXY_CLASS_FLAG) != -1;
	}
	/**
	 * 根据字段生成 对应的get方法名字
	 * @param field
	 * @return
	 */
	public static String genGetMethodNameByField(Field field) {
		String fieldName = field.getName();
		StringBuilder buffer = new StringBuilder();
		buffer.append("get");
		buffer.append(String.valueOf(fieldName.charAt(0)).toUpperCase());
		buffer.append(fieldName.substring(1));
		return buffer.toString();
	}
	
	/**
	 * 根据字段生成 对应的get方法名字
	 * @param field
	 * @return
	 */
	public static String genSetMethodNameByField(Field field) {
		String fieldName = field.getName();
		StringBuilder buffer = new StringBuilder();
		buffer.append("set");
		buffer.append(String.valueOf(fieldName.charAt(0)).toUpperCase());
		buffer.append(fieldName.substring(1));
		return buffer.toString();
	}
	
	/**
	 * 获取持久化对象的主键
	 * @param entity
	 * @return
	 * @throws ORMException
	 */
//	public static String getKeyFromObject(StorableModel entity) throws ORMException {
//
//		ClassInfo classInfo = ReflectionUtil.getClassInfo(entity.getClass());
//		if(classInfo != null) {
//			Field key = classInfo.getIdField().getField();
//			if(key == null) {
//				throw new ORMException("对象主键为空");
//			}
//			Object value = null;
//			try {
//				value = key.get(entity);
//				if(value == null || StringUtils.isNullOrEmpty(value.toString())) {
//					throw new ORMException("key值不能为空");
//				}
//			} catch (Exception e) {
//				e.printStackTrace();
//				throw new ORMException(e);
//			}
//			return value.toString();
//		}
//		return null;
//	}
	
	public static void main(String[] args) throws Exception {
		
		
//		System.out.println(int[][].class.isArray());
//		ClassHelper ch = new ClassHelper();
//		Field f = ClassHelper.class.getField("tmp");
		
		String abc = "com.app:Test3$$EnhancerByCGLIB$$1a600fa5";
//		T t = new T();
		String s = abc.substring(0,abc.indexOf(":"));
		System.out.println(abc.substring(s.length() + 1));
		Map<String,List<String>> map = new HashMap<String, List<String>>();
		List<String> lst = new ArrayList<String>();
		lst.add("asd");
		lst.add("asd");
		lst.add("asd");
		lst.add("asd");
		lst.add("asd");
		
		map.put("asdf", lst);
		map.put("as1df", lst);
		map.put("a2sdf", lst);
		map.put("as3df", lst);
		map.put("as4df", lst);
		Map<String,String> map2 = new HashMap<String, String>();
		map2.put("a", "a");
		map2.put("b", "b");
		map2.put("c", "c");
		map2.put("d", "d");
		map2.put("e", "e");
		Test t = new Test();
		t.setA("a");
		t.setB("b");
		t.setC("c");
		t.setD("d");
		t.setE("e");
		System.out.println("map:"+JSONUtil.toJSON(map2));
		System.out.println("test:"+JSONUtil.toJSON(t));
		String json = "{\"d\":\"d\",\"e\":\"e\",\"b\":\"b\",\"c\":\"c\",\"a\":\"a\"}";
		long b = System.currentTimeMillis();
		for(int i=0;i<10000000;i++) {
			JSONUtil.toObject(json, Map.class);
//			//ClassHelper.class.getField("tmp").set(ch, 1);
//			//f.set(ch, 1);
//			//abc.indexOf("EnhancerByCGLIB");
//			//T.class.isAnnotationPresent(ServiceClientVisible.class);
//			if(t instanceof ActiveRecord) {
//				
			}
//			//T.class.isAssignableFrom(ActiveRecord.class);
//		}
		System.out.println(System.currentTimeMillis() - b);
//		String abc = "adddddddddddddddddddddddddddddddddddddddddddddbc";
//		String abc2 = new String("adddddddddddddddddddddddddddddddddddddddddddddbc");
		//Map<String,String> map = new HashMap<String, String>();
//		map.put("abc", "asdfa");
//		map.put("ab1c", "asdfa");
//		map.put("a2bc", "asdfa");
//		map.put("abec", "asdfa");
//		map.put("ab3c", "asdfa");
//		map.put("ab4c", "asdfa");
//		map.put("ab5c", "asdfa");
//		map.put("ab6c", "asdfa");
//		map.put("a8bc", "asdfa");
//		long b = System.currentTimeMillis();
//		char c = abc.charAt(0);
//		for(int i=0;i<100000;i++) {
//			//abc.replace(String.valueOf(abc.charAt(0)), String.valueOf(c).toUpperCase());//300多毫秒
//			//abc.equals(abc2);
//			map.get(abc);
////			StringBuilder sb = new StringBuilder();
////			sb.append("get");
////			sb.append(Character.toTitleCase(c));
////			sb.append(abc.substring(1));
//		}
		//System.out.println(System.currentTimeMillis() - b);
//		System.out.println(float[].class.getName());
//		System.out.println(Float[][].class.getName());
//		System.out.println(int[][].class.getName());
//		System.out.println(Integer[][].class.getName());
//		System.out.println(long[][].class.getName());
//		System.out.println(Long[][].class.getName());
//		System.out.println(double[][].class.getName());
//		System.out.println(Double[][].class.getName());
//		System.out.println(short[][].class.getName());
//		System.out.println(Short[][].class.getName());
//		System.out.println(boolean[][].class.getName());
//		System.out.println(Boolean[][].class.getName());
//		System.out.println(Character[][].class.getName());
//		System.out.println(char[][].class.getName());
//		System.out.println(Byte[][].class.getName());
//		System.out.println(byte[][].class.getName());
//		float[][] tmp = new float[3][];
//		float[] t2 = new float[1];
//		t2[0] = 1;
//		tmp[0] = t2;
//		List<String> lst = new ArrayList<String>();
//		lst.add("test");
//		lst.add("test1");
//		map.put("m1", "m11");
//		map.put("m2", "m22");
//		Set<String> set = new HashSet<String>();
//		set.add("sss");
//		Map root = new HashMap();
//		root.put("field1", tmp);
//		root.put("field2", lst);
//		root.put("field3", map);
//		root.put("field4", set);
//		String rt = JSONUtil.toJSON(root);
//		Map m = JSONUtil.toMap(rt);
//		Object obj = m.get("field4");
//		//float[][] t = JSONUtil.toObject(obj.toString(), (Class<float[][]>)float[][].class);
//		System.out.println(rt);
	}
}

class Test {
	private String a;
	private String b;
	private String c;
	private String d;
	private String e;
	public String getA() {
		return a;
	}
	public void setA(String a) {
		this.a = a;
	}
	public String getB() {
		return b;
	}
	public void setB(String b) {
		this.b = b;
	}
	public String getC() {
		return c;
	}
	public void setC(String c) {
		this.c = c;
	}
	public String getD() {
		return d;
	}
	public void setD(String d) {
		this.d = d;
	}
	public String getE() {
		return e;
	}
	public void setE(String e) {
		this.e = e;
	}
	
}